import * as THREE from 'three';
import { PhysicsWorld } from '../utils/PhysicsWorld';
import { Debug } from '../utils/Debug';

export class Terrain {
  private scene: THREE.Scene;
  private physics: PhysicsWorld;
  private ground: THREE.Mesh;
  private obstacles: THREE.Object3D[] = [];
  private obstacleColliders: any[] = [];
  private mapSize: number = 40;
  
  constructor(scene: THREE.Scene, physics: PhysicsWorld) {
    this.scene = scene;
    this.physics = physics;
    
    // 创建地面
    this.createGround();
    
    // 创建边界
    this.createBoundaries();
    
    // 创建随机障碍物
    this.createRandomObstacles();
    
    Debug.log('地形已创建');
  }
  
  private createGround(): void {
    // 创建地面
    const groundGeometry = new THREE.PlaneGeometry(this.mapSize, this.mapSize, 32, 32);
    const groundMaterial = new THREE.MeshStandardMaterial({
      color: 0x669933,
      roughness: 0.8,
      metalness: 0.2
    });
    
    this.ground = new THREE.Mesh(groundGeometry, groundMaterial);
    this.ground.rotation.x = -Math.PI / 2;
    this.ground.receiveShadow = true;
    this.scene.add(this.ground);
    
    // 创建网格线（仅在调试模式下可见）
    const gridHelper = new THREE.GridHelper(this.mapSize, 20, 0x000000, 0x000000);
    gridHelper.position.y = 0.01;
    gridHelper.material.opacity = 0.2;
    gridHelper.material.transparent = true;
    this.scene.add(gridHelper);
  }
  
  private createBoundaries(): void {
    // 创建边界墙
    const wallHeight = 2;
    const wallThickness = 1;
    const halfSize = this.mapSize / 2;
    
    // 材质
    const wallMaterial = new THREE.MeshStandardMaterial({
      color: 0x888888,
      roughness: 0.7,
      metalness: 0.2
    });
    
    // 北墙
    const northWallGeometry = new THREE.BoxGeometry(this.mapSize + wallThickness * 2, wallHeight, wallThickness);
    const northWall = new THREE.Mesh(northWallGeometry, wallMaterial);
    northWall.position.set(0, wallHeight / 2, -halfSize - wallThickness / 2);
    northWall.receiveShadow = true;
    northWall.castShadow = true;
    this.scene.add(northWall);
    
    // 添加北墙碰撞体
    this.physics.addCollider(
      northWall,
      new THREE.Vector3(this.mapSize + wallThickness * 2, wallHeight, wallThickness),
      northWall.position,
      0,
      'wall'
    );
    
    // 南墙
    const southWall = northWall.clone();
    southWall.position.z = halfSize + wallThickness / 2;
    this.scene.add(southWall);
    
    // 添加南墙碰撞体
    this.physics.addCollider(
      southWall,
      new THREE.Vector3(this.mapSize + wallThickness * 2, wallHeight, wallThickness),
      southWall.position,
      0,
      'wall'
    );
    
    // 东墙
    const eastWallGeometry = new THREE.BoxGeometry(wallThickness, wallHeight, this.mapSize);
    const eastWall = new THREE.Mesh(eastWallGeometry, wallMaterial);
    eastWall.position.set(halfSize + wallThickness / 2, wallHeight / 2, 0);
    eastWall.receiveShadow = true;
    eastWall.castShadow = true;
    this.scene.add(eastWall);
    
    // 添加东墙碰撞体
    this.physics.addCollider(
      eastWall,
      new THREE.Vector3(wallThickness, wallHeight, this.mapSize),
      eastWall.position,
      0,
      'wall'
    );
    
    // 西墙
    const westWall = eastWall.clone();
    westWall.position.x = -halfSize - wallThickness / 2;
    this.scene.add(westWall);
    
    // 添加西墙碰撞体
    this.physics.addCollider(
      westWall,
      new THREE.Vector3(wallThickness, wallHeight, this.mapSize),
      westWall.position,
      0,
      'wall'
    );
  }
  
  private createRandomObstacles(): void {
    // 创建随机障碍物
    const obstacleCount = 20; // 增加障碍物数量
    
    // 定义不同类型的障碍物
    for (let i = 0; i < obstacleCount; i++) {
      // 随机位置（避开中心区域，玩家出生点）
      let x, z;
      do {
        x = (Math.random() * this.mapSize - this.mapSize / 2) * 0.9;
        z = (Math.random() * this.mapSize - this.mapSize / 2) * 0.9;
      } while (Math.sqrt(x * x + z * z) < 6); // 确保障碍物不在出生点附近
      
      // 随机选择障碍物类型
      const obstacleType = Math.floor(Math.random() * 5); // 0: 方块, 1: 桶, 2: 障碍物, 3: 树, 4: 岩石
      let obstacle: THREE.Mesh | THREE.Group;
      let size: THREE.Vector3;
      
      switch (obstacleType) {
        case 0: // 方块
          {
            const boxSize = 1 + Math.random() * 0.5;
            const boxHeight = 1 + Math.random() * 1;
            const geometry = new THREE.BoxGeometry(boxSize, boxHeight, boxSize);
            const material = new THREE.MeshStandardMaterial({
              color: 0xaa7744,
              roughness: 0.8,
              metalness: 0.2
            });
            
            obstacle = new THREE.Mesh(geometry, material);
            size = new THREE.Vector3(boxSize, boxHeight, boxSize);
          }
          break;
          
        case 1: // 桶
          {
            const radius = 0.5 + Math.random() * 0.3;
            const height = 1.2 + Math.random() * 0.3;
            const geometry = new THREE.CylinderGeometry(radius, radius, height, 16);
            const material = new THREE.MeshStandardMaterial({
              color: 0x887766,
              roughness: 0.6,
              metalness: 0.4
            });
            
            obstacle = new THREE.Mesh(geometry, material);
            size = new THREE.Vector3(radius * 2, height, radius * 2);
          }
          break;
          
        case 2: // 障碍物/堡垒
          {
            const barrierWidth = 2 + Math.random() * 1;
            const barrierHeight = 0.8 + Math.random() * 0.4;
            const barrierDepth = 0.5;
            const geometry = new THREE.BoxGeometry(barrierWidth, barrierHeight, barrierDepth);
            const material = new THREE.MeshStandardMaterial({
              color: 0x999999,
              roughness: 0.7,
              metalness: 0.3
            });
            
            obstacle = new THREE.Mesh(geometry, material);
            size = new THREE.Vector3(barrierWidth, barrierHeight, barrierDepth);
            
            // 随机旋转障碍物
            obstacle.rotation.y = Math.random() * Math.PI;
          }
          break;

        case 3: // 树
          {
            // 创建一个组来包含树干和树冠
            const treeGroup = new THREE.Group();
            
            // 树干
            const trunkRadius = 0.2 + Math.random() * 0.1;
            const trunkHeight = 1.0 + Math.random() * 0.5;
            const trunkGeometry = new THREE.CylinderGeometry(trunkRadius, trunkRadius * 1.2, trunkHeight, 8);
            const trunkMaterial = new THREE.MeshStandardMaterial({
              color: 0x8B4513,
              roughness: 0.9,
              metalness: 0.1
            });
            const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
            trunk.position.y = trunkHeight / 2;
            trunk.castShadow = true;
            treeGroup.add(trunk);
            
            // 树冠 - 使用锥形或球形
            const treeType = Math.random() > 0.5;
            let foliageGeometry;
            if (treeType) {
              // 针叶树 - 锥形
              foliageGeometry = new THREE.ConeGeometry(trunkRadius * 5, trunkHeight * 1.5, 8);
            } else {
              // 阔叶树 - 球形
              foliageGeometry = new THREE.SphereGeometry(trunkRadius * 6, 8, 8);
            }
            
            const foliageMaterial = new THREE.MeshStandardMaterial({
              color: treeType ? 0x006400 : 0x228B22, // 不同类型的树有不同颜色
              roughness: 1.0,
              metalness: 0.0
            });
            
            const foliage = new THREE.Mesh(foliageGeometry, foliageMaterial);
            foliage.position.y = trunkHeight + (treeType ? trunkHeight * 0.75 : 0);
            foliage.castShadow = true;
            treeGroup.add(foliage);
            
            obstacle = treeGroup;
            size = new THREE.Vector3(trunkRadius * 10, trunkHeight * 2.5, trunkRadius * 10);
          }
          break;

        case 4: // 岩石
          {
            // 创建不规则的岩石
            const rockGroup = new THREE.Group();
            
            // 主体岩石
            const rockSize = 0.7 + Math.random() * 0.6;
            const rockHeight = 0.5 + Math.random() * 0.4;
            
            // 使用几个不同的几何体组合成一个岩石
            for (let j = 0; j < 3 + Math.floor(Math.random() * 3); j++) {
              const rockGeometry = Math.random() > 0.5 ?
                new THREE.TetrahedronGeometry(rockSize * (0.6 + Math.random() * 0.4)) :
                new THREE.DodecahedronGeometry(rockSize * (0.6 + Math.random() * 0.4), 0);
              
              const grayShade = 0.5 + Math.random() * 0.3;
              const rockMaterial = new THREE.MeshStandardMaterial({
                color: new THREE.Color(grayShade, grayShade, grayShade),
                roughness: 0.9,
                metalness: 0.1
              });
              
              const rockPiece = new THREE.Mesh(rockGeometry, rockMaterial);
              
              // 随机位置和旋转
              rockPiece.position.set(
                (Math.random() - 0.5) * rockSize,
                rockHeight * Math.random(),
                (Math.random() - 0.5) * rockSize
              );
              
              rockPiece.rotation.set(
                Math.random() * Math.PI * 2,
                Math.random() * Math.PI * 2,
                Math.random() * Math.PI * 2
              );
              
              rockPiece.scale.set(
                0.7 + Math.random() * 0.6,
                0.7 + Math.random() * 0.6,
                0.7 + Math.random() * 0.6
              );
              
              rockPiece.castShadow = true;
              rockPiece.receiveShadow = true;
              
              rockGroup.add(rockPiece);
            }
            
            obstacle = rockGroup;
            size = new THREE.Vector3(rockSize * 2, rockHeight * 2, rockSize * 2);
          }
          break;
      }
      
      // 设置位置
      obstacle.position.set(x, size.y / 2, z);
      obstacle.castShadow = true;
      obstacle.receiveShadow = true;
      
      // 添加到场景
      this.scene.add(obstacle);
      this.obstacles.push(obstacle);
      
      // 添加物理碰撞体
      this.addObstacleCollider(obstacle, size);
    }
    
    // 添加障碍物群组
    this.createObstacleGroups();
  }
  
  // 创建障碍物群组，形成有趣的地形特征
  private createObstacleGroups(): void {
    // 添加2-3个障碍物群组
    const groupCount = 2 + Math.floor(Math.random() * 2);
    
    for (let g = 0; g < groupCount; g++) {
      // 随机选择群组类型: 0 = 森林, 1 = 岩石群
      const groupType = Math.floor(Math.random() * 2);
      
      // 随机群组位置（避开中央区域）
      let groupX, groupZ;
      do {
        groupX = (Math.random() * this.mapSize - this.mapSize / 2) * 0.7;
        groupZ = (Math.random() * this.mapSize - this.mapSize / 2) * 0.7;
      } while (Math.sqrt(groupX * groupX + groupZ * groupZ) < 12);
      
      // 确定群组中障碍物的数量
      const itemCount = 5 + Math.floor(Math.random() * 5);
      
      for (let i = 0; i < itemCount; i++) {
        // 在群组中心周围随机位置
        const angle = Math.random() * Math.PI * 2;
        const distance = 1 + Math.random() * 3;
        const x = groupX + Math.cos(angle) * distance;
        const z = groupZ + Math.sin(angle) * distance;
        
        let obstacle: THREE.Mesh | THREE.Group;
        let size: THREE.Vector3;
        
        if (groupType === 0) { // 森林
          // 创建树
          const treeGroup = new THREE.Group();
          
          // 树干
          const trunkRadius = 0.2 + Math.random() * 0.1;
          const trunkHeight = 1.0 + Math.random() * 0.5;
          const trunkGeometry = new THREE.CylinderGeometry(trunkRadius, trunkRadius * 1.2, trunkHeight, 8);
          const trunkMaterial = new THREE.MeshStandardMaterial({
            color: 0x8B4513,
            roughness: 0.9,
            metalness: 0.1
          });
          const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
          trunk.position.y = trunkHeight / 2;
          trunk.castShadow = true;
          treeGroup.add(trunk);
          
          // 树冠
          const foliageGeometry = new THREE.SphereGeometry(trunkRadius * 6, 8, 8);
          const foliageMaterial = new THREE.MeshStandardMaterial({
            color: 0x228B22,
            roughness: 1.0,
            metalness: 0.0
          });
          
          const foliage = new THREE.Mesh(foliageGeometry, foliageMaterial);
          foliage.position.y = trunkHeight;
          foliage.castShadow = true;
          treeGroup.add(foliage);
          
          obstacle = treeGroup;
          size = new THREE.Vector3(trunkRadius * 10, trunkHeight * 2, trunkRadius * 10);
        } else { // 岩石群
          // 创建岩石
          const rockGroup = new THREE.Group();
          
          const rockSize = 0.5 + Math.random() * 0.4;
          const rockHeight = 0.4 + Math.random() * 0.3;
          
          for (let j = 0; j < 2 + Math.floor(Math.random() * 2); j++) {
            const rockGeometry = Math.random() > 0.5 ?
              new THREE.TetrahedronGeometry(rockSize * (0.6 + Math.random() * 0.4)) :
              new THREE.DodecahedronGeometry(rockSize * (0.6 + Math.random() * 0.4), 0);
            
            const grayShade = 0.5 + Math.random() * 0.3;
            const rockMaterial = new THREE.MeshStandardMaterial({
              color: new THREE.Color(grayShade, grayShade, grayShade),
              roughness: 0.9,
              metalness: 0.1
            });
            
            const rockPiece = new THREE.Mesh(rockGeometry, rockMaterial);
            
            rockPiece.position.set(
              (Math.random() - 0.5) * rockSize,
              rockHeight * Math.random(),
              (Math.random() - 0.5) * rockSize
            );
            
            rockPiece.rotation.set(
              Math.random() * Math.PI * 2,
              Math.random() * Math.PI * 2,
              Math.random() * Math.PI * 2
            );
            
            rockPiece.castShadow = true;
            rockPiece.receiveShadow = true;
            
            rockGroup.add(rockPiece);
          }
          
          obstacle = rockGroup;
          size = new THREE.Vector3(rockSize * 2, rockHeight * 2, rockSize * 2);
        }
        
        // 设置位置
        obstacle.position.set(x, size.y / 2, z);
        obstacle.castShadow = true;
        obstacle.receiveShadow = true;
        
        // 添加到场景
        this.scene.add(obstacle);
        this.obstacles.push(obstacle);
        
        // 添加物理碰撞体
        this.addObstacleCollider(obstacle, size);
      }
    }
  }
  
  private addObstacleCollider(obstacle: THREE.Object3D, size: THREE.Vector3): void {
    const collider = this.physics.addBoxCollider(
      obstacle,
      size,
      obstacle.position,
      obstacle.rotation.y,
      'obstacle'
    );
    
    this.obstacleColliders.push(collider);
  }
  
  public dispose(): void {
    // 从场景中移除障碍物
    this.obstacles.forEach(obstacle => {
      this.scene.remove(obstacle);
    });
    
    // 移除物理碰撞体
    this.obstacleColliders.forEach(collider => {
      this.physics.removeCollider(collider);
    });
    
    // 从场景中移除地面
    this.scene.remove(this.ground);
    
    Debug.log('地形资源已清理');
  }
} 